
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/io.h>


//led4
#define GPF3CON 0x114001E0
#define GPF3DAT 0x114001E4
unsigned int * ptr_con_led;
unsigned int * ptr_dat_led;
void led4_init(void){
	ptr_con_led = ioremap(GPF3CON,4);
	ptr_dat_led = ioremap(GPF3DAT,4);

	*ptr_con_led &= ~(0xf<<16);
	*ptr_con_led |=(0x1 << 16);
}
void led4_on(void){
	 printk("led4 on \n");
	*ptr_dat_led |= 0x1 <<4;
}
void led4_off(void){
	*ptr_dat_led &= ~(0x1 << 4);
	 printk("led4 off \n");
}

//key
#define KEY_ON _IO('L',0)
long my_ioctl (struct file *fl, unsigned int cmd, unsigned long args);

#define GPF1CON 0x11000C20
#define GPF1DAT 0x11000C24
unsigned int * ptr_con;
unsigned int * ptr_dat;
void key2_init(void){
	ptr_con = ioremap(GPF1CON,4);
	ptr_dat = ioremap(GPF1DAT,4);

	*ptr_con &= ~(0xf<<4);
}
void key_on(void){
	if ((*ptr_dat>>1)%2)
    {
   
    led4_off();
    }else{
 led4_on();  
	}
   
   
}



//基于内核模块 搭建字符设备驱动框架

dev_t dev_num;   		//设备号
char *name = "mydev"; 	//设备名
struct cdev mycdev;   	//字符设备对象

// //在设备驱动中 实现open方法
// int myopen(struct inode *pi, struct file *pf);
// //ssize_t myread (struct file * fi, char __user * usr, size_t t, loff_t *lf);
// int myclose (struct inode * id, struct file *fl);
struct file_operations myfops = {  //字符设备操作集
	// .open = myopen,
	// //.read = myread,
	// .release = myclose,
	.unlocked_ioctl = my_ioctl,
};


#define MA  126 
#define MI  0

static int mod_init(void)
{
	int ret;
	dev_num = MKDEV(MA,MI);  //生成一个设备号

	//1.申请设备号
	ret = register_chrdev_region(dev_num,1,name);
	if(ret){
		printk("register_chrdev_region failed\n");
		return ret;
	}

	//2.cdev初始化
	cdev_init(&mycdev,&myfops); 


	//3.将cdev添加到内核中
	ret = cdev_add(&mycdev,dev_num,1);
	if(ret){
		printk("cdev_add failed\n");
		return ret;
	}

	printk("create chrdev success %d,%d\n",MA,MI);
	led4_init();
	key2_init();
	return 0;
}
static void mod_exit(void)
{
	//1.删除cdev
	cdev_del(&mycdev);

	//2.注销设备号
	unregister_chrdev_region(dev_num,1);

	return ;
}


module_init(mod_init);
module_exit(mod_exit);
MODULE_LICENSE("GPL");


// int myopen(struct inode *pi, struct file *pf)
// {
// 	printk("myopen  led4 turn on\n");
// 	led4_on();

// 	return 0;
// }
// // ssize_t myread (struct file * fi, char __user * usr, size_t t, loff_t *lf){
// // 	printk("myread\n");
// // 	return 0;
// // }
// int myclose (struct inode * id, struct file *fl){
// 	printk("myclose led4 turn off\n");
// 	led4_off();
// 	return 0;
// } 

long my_ioctl (struct file *fl, unsigned int cmd, unsigned long args)
{
	printk("my_ioctl:%d %d\n",cmd,*ptr_dat);
	switch (cmd)
	{
	case KEY_ON:
		key_on();
		break;
	default:
		printk("cmd  error\n");
		break;
	}
	return 0;
}
